home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / inetutil.1 / inetutil / inetutils-1.1 / telnetd / sys_term.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-22  |  46.7 KB  |  2,289 lines

  1. /*
  2.  * Copyright (c) 1989, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)sys_term.c    8.4 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #ifdef HAVE_CONFIG_H
  39. #include <config.h>
  40. #endif
  41.  
  42. #include "telnetd.h"
  43.  
  44. #include <paths.h>
  45.  
  46. #if    defined(AUTHENTICATION)
  47. #include <libtelnet/auth.h>
  48. #endif
  49.  
  50. #if defined(CRAY) || defined(__hpux)
  51. # define PARENT_DOES_UTMP
  52. #endif
  53.  
  54. #ifdef    NEWINIT
  55. #include <initreq.h>
  56. int    utmp_len = MAXHOSTNAMELEN;    /* sizeof(init_request.host) */
  57. #else    /* NEWINIT*/
  58. # ifdef    UTMPX
  59. # include <utmpx.h>
  60. struct    utmpx wtmp;
  61. # else
  62. # include <utmp.h>
  63. struct    utmp wtmp;
  64. # endif /* UTMPX */
  65.  
  66. int    utmp_len = sizeof(wtmp.ut_host);
  67. # ifndef PARENT_DOES_UTMP
  68. char    wtmpf[]    = "/usr/adm/wtmp";
  69. char    utmpf[] = "/etc/utmp";
  70. # else /* PARENT_DOES_UTMP */
  71. char    wtmpf[]    = "/etc/wtmp";
  72. # endif /* PARENT_DOES_UTMP */
  73.  
  74. # ifdef CRAY
  75. #include <tmpdir.h>
  76. #include <sys/wait.h>
  77. #  if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
  78. #   define UNICOS7x
  79. #  endif
  80.  
  81. #  ifdef UNICOS7x
  82. #include <sys/sysv.h>
  83. #include <sys/secstat.h>
  84. extern int secflag;
  85. extern struct sysv sysv;
  86. #  endif /* UNICOS7x */
  87. # endif    /* CRAY */
  88. #endif    /* NEWINIT */
  89.  
  90. #ifdef    STREAMSPTY
  91. #include <sac.h>
  92. #include <sys/stropts.h>
  93. #endif
  94.  
  95. #define SCPYN(a, b)    (void) strncpy(a, b, sizeof(a))
  96. #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
  97.  
  98. #ifdef    STREAMS
  99. #include <sys/stream.h>
  100. #endif
  101. #ifdef __hpux
  102. #include <sys/resource.h>
  103. #include <sys/proc.h>
  104. #endif
  105. #ifdef HAVE_SYS_TTY_H
  106. #include <sys/tty.h>
  107. #endif
  108. #ifdef    t_erase
  109. #undef    t_erase
  110. #undef    t_kill
  111. #undef    t_intrc
  112. #undef    t_quitc
  113. #undef    t_startc
  114. #undef    t_stopc
  115. #undef    t_eofc
  116. #undef    t_brkc
  117. #undef    t_suspc
  118. #undef    t_dsuspc
  119. #undef    t_rprntc
  120. #undef    t_flushc
  121. #undef    t_werasc
  122. #undef    t_lnextc
  123. #endif
  124.  
  125. #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
  126. # define EXTPROC 0400
  127. #endif
  128.  
  129. #ifndef    USE_TERMIO
  130. struct termbuf {
  131.     struct sgttyb sg;
  132.     struct tchars tc;
  133.     struct ltchars ltc;
  134.     int state;
  135.     int lflags;
  136. } termbuf, termbuf2;
  137. # define    cfsetospeed(tp, val)    (tp)->sg.sg_ospeed = (val)
  138. # define    cfsetispeed(tp, val)    (tp)->sg.sg_ispeed = (val)
  139. # define    cfgetospeed(tp)        (tp)->sg.sg_ospeed
  140. # define    cfgetispeed(tp)        (tp)->sg.sg_ispeed
  141. #else    /* USE_TERMIO */
  142. # ifdef    SYSV_TERMIO
  143. #    define termios termio
  144. # endif
  145. # ifndef    TCSANOW
  146. #  ifdef TCSETS
  147. #   define    TCSANOW        TCSETS
  148. #   define    TCSADRAIN    TCSETSW
  149. #   define    tcgetattr(f, t)    ioctl(f, TCGETS, (char *)t)
  150. #  else
  151. #   ifdef TCSETA
  152. #    define    TCSANOW        TCSETA
  153. #    define    TCSADRAIN    TCSETAW
  154. #    define    tcgetattr(f, t)    ioctl(f, TCGETA, (char *)t)
  155. #   else
  156. #    define    TCSANOW        TIOCSETA
  157. #    define    TCSADRAIN    TIOCSETAW
  158. #    define    tcgetattr(f, t)    ioctl(f, TIOCGETA, (char *)t)
  159. #   endif
  160. #  endif
  161. #  define    tcsetattr(f, a, t)    ioctl(f, a, t)
  162. #  define    cfsetospeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
  163.                     (tp)->c_cflag |= (val)
  164. #  define    cfgetospeed(tp)        ((tp)->c_cflag & CBAUD)
  165. #  ifdef CIBAUD
  166. #   define    cfsetispeed(tp, val)    (tp)->c_cflag &= ~CIBAUD; \
  167.                     (tp)->c_cflag |= ((val)<<IBSHIFT)
  168. #   define    cfgetispeed(tp)        (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
  169. #  else
  170. #   define    cfsetispeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
  171.                     (tp)->c_cflag |= (val)
  172. #   define    cfgetispeed(tp)        ((tp)->c_cflag & CBAUD)
  173. #  endif
  174. # endif /* TCSANOW */
  175. struct termios termbuf, termbuf2;    /* pty control structure */
  176. # ifdef  STREAMSPTY
  177. int ttyfd = -1;
  178. # endif
  179. #endif    /* USE_TERMIO */
  180.  
  181. /*
  182.  * init_termbuf()
  183.  * copy_termbuf(cp)
  184.  * set_termbuf()
  185.  *
  186.  * These three routines are used to get and set the "termbuf" structure
  187.  * to and from the kernel.  init_termbuf() gets the current settings.
  188.  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
  189.  * set_termbuf() writes the structure into the kernel.
  190.  */
  191.  
  192.     void
  193. init_termbuf()
  194. {
  195. #ifndef    USE_TERMIO
  196.     (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
  197.     (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
  198.     (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
  199. # ifdef    TIOCGSTATE
  200.     (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
  201. # endif
  202. #else
  203. # ifdef  STREAMSPTY
  204.     (void) tcgetattr(ttyfd, &termbuf);
  205. # else
  206.     (void) tcgetattr(pty, &termbuf);
  207. # endif
  208. #endif
  209.     termbuf2 = termbuf;
  210. }
  211.  
  212. #if    defined(LINEMODE) && defined(TIOCPKT_IOCTL)
  213.     void
  214. copy_termbuf(cp, len)
  215.     char *cp;
  216.     int len;
  217. {
  218.     if (len > sizeof(termbuf))
  219.         len = sizeof(termbuf);
  220.     memmove((char *)&termbuf, cp, len);
  221.     termbuf2 = termbuf;
  222. }
  223. #endif    /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
  224.  
  225.     void
  226. set_termbuf()
  227. {
  228.     /*
  229.      * Only make the necessary changes.
  230.      */
  231. #ifndef    USE_TERMIO
  232.     if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
  233.                             sizeof(termbuf.sg)))
  234.         (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
  235.     if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
  236.                             sizeof(termbuf.tc)))
  237.         (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
  238.     if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
  239.                             sizeof(termbuf.ltc)))
  240.         (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
  241.     if (termbuf.lflags != termbuf2.lflags)
  242.         (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
  243. #else    /* USE_TERMIO */
  244.     if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
  245. # ifdef  STREAMSPTY
  246.         (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
  247. # else
  248.         (void) tcsetattr(pty, TCSANOW, &termbuf);
  249. # endif
  250. # if    defined(CRAY2) && defined(UNICOS5)
  251.     needtermstat = 1;
  252. # endif
  253. #endif    /* USE_TERMIO */
  254. }
  255.  
  256.  
  257. /*
  258.  * spcset(func, valp, valpp)
  259.  *
  260.  * This function takes various special characters (func), and
  261.  * sets *valp to the current value of that character, and
  262.  * *valpp to point to where in the "termbuf" structure that
  263.  * value is kept.
  264.  *
  265.  * It returns the SLC_ level of support for this function.
  266.  */
  267.  
  268. #ifndef    USE_TERMIO
  269.     int
  270. spcset(func, valp, valpp)
  271.     int func;
  272.     cc_t *valp;
  273.     cc_t **valpp;
  274. {
  275.     switch(func) {
  276.     case SLC_EOF:
  277.         *valp = termbuf.tc.t_eofc;
  278.         *valpp = (cc_t *)&termbuf.tc.t_eofc;
  279.         return(SLC_VARIABLE);
  280.     case SLC_EC:
  281.         *valp = termbuf.sg.sg_erase;
  282.         *valpp = (cc_t *)&termbuf.sg.sg_erase;
  283.         return(SLC_VARIABLE);
  284.     case SLC_EL:
  285.         *valp = termbuf.sg.sg_kill;
  286.         *valpp = (cc_t *)&termbuf.sg.sg_kill;
  287.         return(SLC_VARIABLE);
  288.     case SLC_IP:
  289.         *valp = termbuf.tc.t_intrc;
  290.         *valpp = (cc_t *)&termbuf.tc.t_intrc;
  291.         return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  292.     case SLC_ABORT:
  293.         *valp = termbuf.tc.t_quitc;
  294.         *valpp = (cc_t *)&termbuf.tc.t_quitc;
  295.         return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  296.     case SLC_XON:
  297.         *valp = termbuf.tc.t_startc;
  298.         *valpp = (cc_t *)&termbuf.tc.t_startc;
  299.         return(SLC_VARIABLE);
  300.     case SLC_XOFF:
  301.         *valp = termbuf.tc.t_stopc;
  302.         *valpp = (cc_t *)&termbuf.tc.t_stopc;
  303.         return(SLC_VARIABLE);
  304.     case SLC_AO:
  305.         *valp = termbuf.ltc.t_flushc;
  306.         *valpp = (cc_t *)&termbuf.ltc.t_flushc;
  307.         return(SLC_VARIABLE);
  308.     case SLC_SUSP:
  309.         *valp = termbuf.ltc.t_suspc;
  310.         *valpp = (cc_t *)&termbuf.ltc.t_suspc;
  311.         return(SLC_VARIABLE);
  312.     case SLC_EW:
  313.         *valp = termbuf.ltc.t_werasc;
  314.         *valpp = (cc_t *)&termbuf.ltc.t_werasc;
  315.         return(SLC_VARIABLE);
  316.     case SLC_RP:
  317.         *valp = termbuf.ltc.t_rprntc;
  318.         *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
  319.         return(SLC_VARIABLE);
  320.     case SLC_LNEXT:
  321.         *valp = termbuf.ltc.t_lnextc;
  322.         *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
  323.         return(SLC_VARIABLE);
  324.     case SLC_FORW1:
  325.         *valp = termbuf.tc.t_brkc;
  326.         *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
  327.         return(SLC_VARIABLE);
  328.     case SLC_BRK:
  329.     case SLC_SYNCH:
  330.     case SLC_AYT:
  331.     case SLC_EOR:
  332.         *valp = (cc_t)0;
  333.         *valpp = (cc_t *)0;
  334.         return(SLC_DEFAULT);
  335.     default:
  336.         *valp = (cc_t)0;
  337.         *valpp = (cc_t *)0;
  338.         return(SLC_NOSUPPORT);
  339.     }
  340. }
  341.  
  342. #else    /* USE_TERMIO */
  343.  
  344.     int
  345. spcset(func, valp, valpp)
  346.     int func;
  347.     cc_t *valp;
  348.     cc_t **valpp;
  349. {
  350.  
  351. #define    setval(a, b)    *valp = termbuf.c_cc[a]; \
  352.             *valpp = &termbuf.c_cc[a]; \
  353.             return(b);
  354. #define    defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
  355.  
  356.     switch(func) {
  357.     case SLC_EOF:
  358.         setval(VEOF, SLC_VARIABLE);
  359.     case SLC_EC:
  360.         setval(VERASE, SLC_VARIABLE);
  361.     case SLC_EL:
  362.         setval(VKILL, SLC_VARIABLE);
  363.     case SLC_IP:
  364.         setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  365.     case SLC_ABORT:
  366.         setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
  367.     case SLC_XON:
  368. #ifdef    VSTART
  369.         setval(VSTART, SLC_VARIABLE);
  370. #else
  371.         defval(0x13);
  372. #endif
  373.     case SLC_XOFF:
  374. #ifdef    VSTOP
  375.         setval(VSTOP, SLC_VARIABLE);
  376. #else
  377.         defval(0x11);
  378. #endif
  379.     case SLC_EW:
  380. #ifdef    VWERASE
  381.         setval(VWERASE, SLC_VARIABLE);
  382. #else
  383.         defval(0);
  384. #endif
  385.     case SLC_RP:
  386. #ifdef    VREPRINT
  387.         setval(VREPRINT, SLC_VARIABLE);
  388. #else
  389.         defval(0);
  390. #endif
  391.     case SLC_LNEXT:
  392. #ifdef    VLNEXT
  393.         setval(VLNEXT, SLC_VARIABLE);
  394. #else
  395.         defval(0);
  396. #endif
  397.     case SLC_AO:
  398. #if    !defined(VDISCARD) && defined(VFLUSHO)
  399. # define VDISCARD VFLUSHO
  400. #endif
  401. #ifdef    VDISCARD
  402.         setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
  403. #else
  404.         defval(0);
  405. #endif
  406.     case SLC_SUSP:
  407. #ifdef    VSUSP
  408.         setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
  409. #else
  410.         defval(0);
  411. #endif
  412. #ifdef    VEOL
  413.     case SLC_FORW1:
  414.         setval(VEOL, SLC_VARIABLE);
  415. #endif
  416. #ifdef    VEOL2
  417.     case SLC_FORW2:
  418.         setval(VEOL2, SLC_VARIABLE);
  419. #endif
  420.     case SLC_AYT:
  421. #ifdef    VSTATUS
  422.         setval(VSTATUS, SLC_VARIABLE);
  423. #else
  424.         defval(0);
  425. #endif
  426.  
  427.     case SLC_BRK:
  428.     case SLC_SYNCH:
  429.     case SLC_EOR:
  430.         defval(0);
  431.  
  432.     default:
  433.         *valp = 0;
  434.         *valpp = 0;
  435.         return(SLC_NOSUPPORT);
  436.     }
  437. }
  438. #endif    /* USE_TERMIO */
  439.  
  440. #ifdef CRAY
  441. /*
  442.  * getnpty()
  443.  *
  444.  * Return the number of pty's configured into the system.
  445.  */
  446.     int
  447. getnpty()
  448. {
  449. #ifdef _SC_CRAY_NPTY
  450.     int numptys;
  451.  
  452.     if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
  453.         return numptys;
  454.     else
  455. #endif /* _SC_CRAY_NPTY */
  456.         return 128;
  457. }
  458. #endif /* CRAY */
  459.  
  460. #ifndef    convex
  461. /*
  462.  * getpty()
  463.  *
  464.  * Allocate a pty.  As a side effect, the external character
  465.  * array "line" contains the name of the slave side.
  466.  *
  467.  * Returns the file descriptor of the opened pty.
  468.  */
  469. #ifndef    __GNUC__
  470. char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  471. #else
  472. static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  473. char *line = Xline;
  474. #endif
  475. #ifdef    CRAY
  476. char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  477. #endif    /* CRAY */
  478.  
  479.     int
  480. getpty(ptynum)
  481. int *ptynum;
  482. {
  483.     register int p;
  484. #ifdef    STREAMSPTY
  485.     int t;
  486.     char *ptsname();
  487.  
  488.     p = open("/dev/ptmx", O_RDWR);
  489.     if (p > 0) {
  490.         grantpt(p);
  491.         unlockpt(p);
  492.         strcpy(line, ptsname(p));
  493.         return(p);
  494.     }
  495.  
  496. #else    /* ! STREAMSPTY */
  497. #ifndef CRAY
  498.     register char *cp, *p1, *p2;
  499.     register int i;
  500. #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
  501.     int dummy;
  502. #endif
  503.  
  504. #ifndef    __hpux
  505.     (void) sprintf(line, "/dev/ptyXX");
  506.     p1 = &line[8];
  507.     p2 = &line[9];
  508. #else
  509.     (void) sprintf(line, "/dev/ptym/ptyXX");
  510.     p1 = &line[13];
  511.     p2 = &line[14];
  512. #endif
  513.  
  514.     for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
  515.         struct stat stb;
  516.  
  517.         *p1 = *cp;
  518.         *p2 = '0';
  519.         /*
  520.          * This stat() check is just to keep us from
  521.          * looping through all 256 combinations if there
  522.          * aren't that many ptys available.
  523.          */
  524.         if (stat(line, &stb) < 0)
  525.             break;
  526.         for (i = 0; i < 16; i++) {
  527.             *p2 = "0123456789abcdef"[i];
  528.             p = open(line, O_RDWR);
  529.             if (p > 0) {
  530. #ifndef    __hpux
  531.                 line[5] = 't';
  532. #else
  533.                 for (p1 = &line[8]; *p1; p1++)
  534.                     *p1 = *(p1+1);
  535.                 line[9] = 't';
  536. #endif
  537.                 chown(line, 0, 0);
  538.                 chmod(line, 0600);
  539. #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
  540.                 if (ioctl(p, TIOCGPGRP, &dummy) == 0
  541.                     || errno != EIO) {
  542.                     chmod(line, 0666);
  543.                     close(p);
  544.                     line[5] = 'p';
  545.                 } else
  546. #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
  547.                     return(p);
  548.             }
  549.         }
  550.     }
  551. #else    /* CRAY */
  552.     extern lowpty, highpty;
  553.     struct stat sb;
  554.  
  555.     for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
  556.         (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
  557.         p = open(myline, O_RDWR);
  558.         if (p < 0)
  559.             continue;
  560.         (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
  561.         /*
  562.          * Here are some shenanigans to make sure that there
  563.          * are no listeners lurking on the line.
  564.          */
  565.         if(stat(line, &sb) < 0) {
  566.             (void) close(p);
  567.             continue;
  568.         }
  569.         if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
  570.             chown(line, 0, 0);
  571.             chmod(line, 0600);
  572.             (void)close(p);
  573.             p = open(myline, O_RDWR);
  574.             if (p < 0)
  575.                 continue;
  576.         }
  577.         /*
  578.          * Now it should be safe...check for accessability.
  579.          */
  580.         if (access(line, 6) == 0)
  581.             return(p);
  582.         else {
  583.             /* no tty side to pty so skip it */
  584.             (void) close(p);
  585.         }
  586.     }
  587. #endif    /* CRAY */
  588. #endif    /* STREAMSPTY */
  589.     return(-1);
  590. }
  591. #endif    /* convex */
  592.  
  593. #ifdef    LINEMODE
  594. /*
  595.  * tty_flowmode()    Find out if flow control is enabled or disabled.
  596.  * tty_linemode()    Find out if linemode (external processing) is enabled.
  597.  * tty_setlinemod(on)    Turn on/off linemode.
  598.  * tty_isecho()        Find out if echoing is turned on.
  599.  * tty_setecho(on)    Enable/disable character echoing.
  600.  * tty_israw()        Find out if terminal is in RAW mode.
  601.  * tty_binaryin(on)    Turn on/off BINARY on input.
  602.  * tty_binaryout(on)    Turn on/off BINARY on output.
  603.  * tty_isediting()    Find out if line editing is enabled.
  604.  * tty_istrapsig()    Find out if signal trapping is enabled.
  605.  * tty_setedit(on)    Turn on/off line editing.
  606.  * tty_setsig(on)    Turn on/off signal trapping.
  607.  * tty_issofttab()    Find out if tab expansion is enabled.
  608.  * tty_setsofttab(on)    Turn on/off soft tab expansion.
  609.  * tty_islitecho()    Find out if typed control chars are echoed literally
  610.  * tty_setlitecho()    Turn on/off literal echo of control chars
  611.  * tty_tspeed(val)    Set transmit speed to val.
  612.  * tty_rspeed(val)    Set receive speed to val.
  613.  */
  614.  
  615. #ifdef convex
  616. static int linestate;
  617. #endif
  618.  
  619.     int
  620. tty_linemode()
  621. {
  622. #ifndef convex
  623. #ifndef    USE_TERMIO
  624.     return(termbuf.state & TS_EXTPROC);
  625. #else
  626.     return(termbuf.c_lflag & EXTPROC);
  627. #endif
  628. #else
  629.     return(linestate);
  630. #endif
  631. }
  632.  
  633.     void
  634. tty_setlinemode(on)
  635.     int on;
  636. {
  637. #ifdef    TIOCEXT
  638. # ifndef convex
  639.     set_termbuf();
  640. # else
  641.     linestate = on;
  642. # endif
  643.     (void) ioctl(pty, TIOCEXT, (char *)&on);
  644. # ifndef convex
  645.     init_termbuf();
  646. # endif
  647. #else    /* !TIOCEXT */
  648. # ifdef    EXTPROC
  649.     if (on)
  650.         termbuf.c_lflag |= EXTPROC;
  651.     else
  652.         termbuf.c_lflag &= ~EXTPROC;
  653. # endif
  654. #endif    /* TIOCEXT */
  655. }
  656. #endif    /* LINEMODE */
  657.  
  658.     int
  659. tty_isecho()
  660. {
  661. #ifndef USE_TERMIO
  662.     return (termbuf.sg.sg_flags & ECHO);
  663. #else
  664.     return (termbuf.c_lflag & ECHO);
  665. #endif
  666. }
  667.  
  668.     int
  669. tty_flowmode()
  670. {
  671. #ifndef USE_TERMIO
  672.     return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
  673. #else
  674.     return((termbuf.c_iflag & IXON) ? 1 : 0);
  675. #endif
  676. }
  677.  
  678.     int
  679. tty_restartany()
  680. {
  681. #ifndef USE_TERMIO
  682. # ifdef    DECCTQ
  683.     return((termbuf.lflags & DECCTQ) ? 0 : 1);
  684. # else
  685.     return(-1);
  686. # endif
  687. #else
  688.     return((termbuf.c_iflag & IXANY) ? 1 : 0);
  689. #endif
  690. }
  691.  
  692.     void
  693. tty_setecho(on)
  694.     int on;
  695. {
  696. #ifndef    USE_TERMIO
  697.     if (on)
  698.         termbuf.sg.sg_flags |= ECHO|CRMOD;
  699.     else
  700.         termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
  701. #else
  702.     if (on)
  703.         termbuf.c_lflag |= ECHO;
  704.     else
  705.         termbuf.c_lflag &= ~ECHO;
  706. #endif
  707. }
  708.  
  709.     int
  710. tty_israw()
  711. {
  712. #ifndef USE_TERMIO
  713.     return(termbuf.sg.sg_flags & RAW);
  714. #else
  715.     return(!(termbuf.c_lflag & ICANON));
  716. #endif
  717. }
  718.  
  719. #if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  720.     int
  721. tty_setraw(on)
  722. {
  723. #  ifndef USE_TERMIO
  724.     if (on)
  725.         termbuf.sg.sg_flags |= RAW;
  726.     else
  727.         termbuf.sg.sg_flags &= ~RAW;
  728. #  else
  729.     if (on)
  730.         termbuf.c_lflag &= ~ICANON;
  731.     else
  732.         termbuf.c_lflag |= ICANON;
  733. #  endif
  734. }
  735. #endif
  736.  
  737.     void
  738. tty_binaryin(on)
  739.     int on;
  740. {
  741. #ifndef    USE_TERMIO
  742.     if (on)
  743.         termbuf.lflags |= LPASS8;
  744.     else
  745.         termbuf.lflags &= ~LPASS8;
  746. #else
  747.     if (on) {
  748.         termbuf.c_iflag &= ~ISTRIP;
  749.     } else {
  750.         termbuf.c_iflag |= ISTRIP;
  751.     }
  752. #endif
  753. }
  754.  
  755.     void
  756. tty_binaryout(on)
  757.     int on;
  758. {
  759. #ifndef    USE_TERMIO
  760.     if (on)
  761.         termbuf.lflags |= LLITOUT;
  762.     else
  763.         termbuf.lflags &= ~LLITOUT;
  764. #else
  765.     if (on) {
  766.         termbuf.c_cflag &= ~(CSIZE|PARENB);
  767.         termbuf.c_cflag |= CS8;
  768.         termbuf.c_oflag &= ~OPOST;
  769.     } else {
  770.         termbuf.c_cflag &= ~CSIZE;
  771.         termbuf.c_cflag |= CS7|PARENB;
  772.         termbuf.c_oflag |= OPOST;
  773.     }
  774. #endif
  775. }
  776.  
  777.     int
  778. tty_isbinaryin()
  779. {
  780. #ifndef    USE_TERMIO
  781.     return(termbuf.lflags & LPASS8);
  782. #else
  783.     return(!(termbuf.c_iflag & ISTRIP));
  784. #endif
  785. }
  786.  
  787.     int
  788. tty_isbinaryout()
  789. {
  790. #ifndef    USE_TERMIO
  791.     return(termbuf.lflags & LLITOUT);
  792. #else
  793.     return(!(termbuf.c_oflag&OPOST));
  794. #endif
  795. }
  796.  
  797. #ifdef    LINEMODE
  798.     int
  799. tty_isediting()
  800. {
  801. #ifndef USE_TERMIO
  802.     return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
  803. #else
  804.     return(termbuf.c_lflag & ICANON);
  805. #endif
  806. }
  807.  
  808.     int
  809. tty_istrapsig()
  810. {
  811. #ifndef USE_TERMIO
  812.     return(!(termbuf.sg.sg_flags&RAW));
  813. #else
  814.     return(termbuf.c_lflag & ISIG);
  815. #endif
  816. }
  817.  
  818.     void
  819. tty_setedit(on)
  820.     int on;
  821. {
  822. #ifndef USE_TERMIO
  823.     if (on)
  824.         termbuf.sg.sg_flags &= ~CBREAK;
  825.     else
  826.         termbuf.sg.sg_flags |= CBREAK;
  827. #else
  828.     if (on)
  829.         termbuf.c_lflag |= ICANON;
  830.     else
  831.         termbuf.c_lflag &= ~ICANON;
  832. #endif
  833. }
  834.  
  835.     void
  836. tty_setsig(on)
  837.     int on;
  838. {
  839. #ifndef    USE_TERMIO
  840.     if (on)
  841.         ;
  842. #else
  843.     if (on)
  844.         termbuf.c_lflag |= ISIG;
  845.     else
  846.         termbuf.c_lflag &= ~ISIG;
  847. #endif
  848. }
  849. #endif    /* LINEMODE */
  850.  
  851.     int
  852. tty_issofttab()
  853. {
  854. #ifndef    USE_TERMIO
  855.     return (termbuf.sg.sg_flags & XTABS);
  856. #else
  857. # ifdef    OXTABS
  858.     return (termbuf.c_oflag & OXTABS);
  859. # endif
  860. # ifdef    TABDLY
  861.     return ((termbuf.c_oflag & TABDLY) == TAB3);
  862. # endif
  863. #endif
  864. }
  865.  
  866.     void
  867. tty_setsofttab(on)
  868.     int on;
  869. {
  870. #ifndef    USE_TERMIO
  871.     if (on)
  872.         termbuf.sg.sg_flags |= XTABS;
  873.     else
  874.         termbuf.sg.sg_flags &= ~XTABS;
  875. #else
  876.     if (on) {
  877. # ifdef    OXTABS
  878.         termbuf.c_oflag |= OXTABS;
  879. # endif
  880. # ifdef    TABDLY
  881.         termbuf.c_oflag &= ~TABDLY;
  882.         termbuf.c_oflag |= TAB3;
  883. # endif
  884.     } else {
  885. # ifdef    OXTABS
  886.         termbuf.c_oflag &= ~OXTABS;
  887. # endif
  888. # ifdef    TABDLY
  889.         termbuf.c_oflag &= ~TABDLY;
  890.         termbuf.c_oflag |= TAB0;
  891. # endif
  892.     }
  893. #endif
  894. }
  895.  
  896.     int
  897. tty_islitecho()
  898. {
  899. #ifndef    USE_TERMIO
  900.     return (!(termbuf.lflags & LCTLECH));
  901. #else
  902. # ifdef    ECHOCTL
  903.     return (!(termbuf.c_lflag & ECHOCTL));
  904. # endif
  905. # ifdef    TCTLECH
  906.     return (!(termbuf.c_lflag & TCTLECH));
  907. # endif
  908. # if    !defined(ECHOCTL) && !defined(TCTLECH)
  909.     return (0);    /* assumes ctl chars are echoed '^x' */
  910. # endif
  911. #endif
  912. }
  913.  
  914.     void
  915. tty_setlitecho(on)
  916.     int on;
  917. {
  918. #ifndef    USE_TERMIO
  919.     if (on)
  920.         termbuf.lflags &= ~LCTLECH;
  921.     else
  922.         termbuf.lflags |= LCTLECH;
  923. #else
  924. # ifdef    ECHOCTL
  925.     if (on)
  926.         termbuf.c_lflag &= ~ECHOCTL;
  927.     else
  928.         termbuf.c_lflag |= ECHOCTL;
  929. # endif
  930. # ifdef    TCTLECH
  931.     if (on)
  932.         termbuf.c_lflag &= ~TCTLECH;
  933.     else
  934.         termbuf.c_lflag |= TCTLECH;
  935. # endif
  936. #endif
  937. }
  938.  
  939.     int
  940. tty_iscrnl()
  941. {
  942. #ifndef    USE_TERMIO
  943.     return (termbuf.sg.sg_flags & CRMOD);
  944. #else
  945.     return (termbuf.c_iflag & ICRNL);
  946. #endif
  947. }
  948.  
  949. /*
  950.  * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
  951.  */
  952. #if B4800 != 4800
  953. #define    DECODE_BAUD
  954. #endif
  955.  
  956. #ifdef    DECODE_BAUD
  957.  
  958. /*
  959.  * A table of available terminal speeds
  960.  */
  961. struct termspeeds {
  962.     int    speed;
  963.     int    value;
  964. } termspeeds[] = {
  965.     { 0,     B0 },    { 50,    B50 },   { 75,    B75 },
  966.     { 110,   B110 },  { 134,   B134 },  { 150,   B150 },
  967.     { 200,   B200 },  { 300,   B300 },  { 600,   B600 },
  968.     { 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
  969.     { 4800,   B4800 },
  970. #ifdef    B7200
  971.     { 7200,  B7200 },
  972. #endif
  973.     { 9600,   B9600 },
  974. #ifdef    B14400
  975.     { 14400,  B14400 },
  976. #endif
  977. #ifdef    B19200
  978.     { 19200,  B19200 },
  979. #endif
  980. #ifdef    B28800
  981.     { 28800,  B28800 },
  982. #endif
  983. #ifdef    B38400
  984.     { 38400,  B38400 },
  985. #endif
  986. #ifdef    B57600
  987.     { 57600,  B57600 },
  988. #endif
  989. #ifdef    B115200
  990.     { 115200, B115200 },
  991. #endif
  992. #ifdef    B230400
  993.     { 230400, B230400 },
  994. #endif
  995.     { -1,     0 }
  996. };
  997. #endif    /* DECODE_BUAD */
  998.  
  999.     void
  1000. tty_tspeed(val)
  1001.     int val;
  1002. {
  1003. #ifdef    DECODE_BAUD
  1004.     register struct termspeeds *tp;
  1005.  
  1006.     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
  1007.         ;
  1008.     if (tp->speed == -1)    /* back up to last valid value */
  1009.         --tp;
  1010.     cfsetospeed(&termbuf, tp->value);
  1011. #else    /* DECODE_BUAD */
  1012.     cfsetospeed(&termbuf, val);
  1013. #endif    /* DECODE_BUAD */
  1014. }
  1015.  
  1016.     void
  1017. tty_rspeed(val)
  1018.     int val;
  1019. {
  1020. #ifdef    DECODE_BAUD
  1021.     register struct termspeeds *tp;
  1022.  
  1023.     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
  1024.         ;
  1025.     if (tp->speed == -1)    /* back up to last valid value */
  1026.         --tp;
  1027.     cfsetispeed(&termbuf, tp->value);
  1028. #else    /* DECODE_BAUD */
  1029.     cfsetispeed(&termbuf, val);
  1030. #endif    /* DECODE_BAUD */
  1031. }
  1032.  
  1033. #if    defined(CRAY2) && defined(UNICOS5)
  1034.     int
  1035. tty_isnewmap()
  1036. {
  1037.     return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
  1038.             !(termbuf.c_oflag & ONLRET));
  1039. }
  1040. #endif
  1041.  
  1042. #ifdef PARENT_DOES_UTMP
  1043. # ifndef NEWINIT
  1044. extern    struct utmp wtmp;
  1045. extern char wtmpf[];
  1046. # else    /* NEWINIT */
  1047. int    gotalarm;
  1048.  
  1049.     /* ARGSUSED */
  1050.     void
  1051. nologinproc(sig)
  1052.     int sig;
  1053. {
  1054.     gotalarm++;
  1055. }
  1056. # endif    /* NEWINIT */
  1057. #endif /* PARENT_DOES_UTMP */
  1058.  
  1059. #ifndef    NEWINIT
  1060. # ifdef PARENT_DOES_UTMP
  1061. extern void utmp_sig_init P((void));
  1062. extern void utmp_sig_reset P((void));
  1063. extern void utmp_sig_wait P((void));
  1064. extern void utmp_sig_notify P((int));
  1065. # endif /* PARENT_DOES_UTMP */
  1066. #endif
  1067.  
  1068. /*
  1069.  * getptyslave()
  1070.  *
  1071.  * Open the slave side of the pty, and do any initialization
  1072.  * that is necessary.  The return value is a file descriptor
  1073.  * for the slave side.
  1074.  */
  1075.     int
  1076. getptyslave()
  1077. {
  1078.     register int t = -1;
  1079.  
  1080. #if    !defined(CRAY) || !defined(NEWINIT)
  1081. # ifdef    LINEMODE
  1082.     int waslm;
  1083. # endif
  1084. # ifdef    TIOCGWINSZ
  1085.     struct winsize ws;
  1086.     extern int def_row, def_col;
  1087. # endif
  1088.     extern int def_tspeed, def_rspeed;
  1089.     /*
  1090.      * Opening the slave side may cause initilization of the
  1091.      * kernel tty structure.  We need remember the state of
  1092.      *     if linemode was turned on
  1093.      *    terminal window size
  1094.      *    terminal speed
  1095.      * so that we can re-set them if we need to.
  1096.      */
  1097. # ifdef    LINEMODE
  1098.     waslm = tty_linemode();
  1099. # endif
  1100.  
  1101.  
  1102.     /*
  1103.      * Make sure that we don't have a controlling tty, and
  1104.      * that we are the session (process group) leader.
  1105.      */
  1106. # ifdef    TIOCNOTTY
  1107.     t = open(_PATH_TTY, O_RDWR);
  1108.     if (t >= 0) {
  1109.         (void) ioctl(t, TIOCNOTTY, (char *)0);
  1110.         (void) close(t);
  1111.     }
  1112. # endif
  1113.  
  1114.  
  1115. # ifdef PARENT_DOES_UTMP
  1116.     /*
  1117.      * Wait for our parent to get the utmp stuff to get done.
  1118.      */
  1119.     utmp_sig_wait();
  1120. # endif
  1121.  
  1122.     t = cleanopen(line);
  1123.     if (t < 0)
  1124.         fatalperror(net, line);
  1125.  
  1126. #ifdef  STREAMSPTY
  1127. #ifdef    USE_TERMIO
  1128.     ttyfd = t;
  1129. #endif
  1130.     if (ioctl(t, I_PUSH, "ptem") < 0) 
  1131.         fatal(net, "I_PUSH ptem");
  1132.     if (ioctl(t, I_PUSH, "ldterm") < 0)
  1133.         fatal(net, "I_PUSH ldterm");
  1134.     if (ioctl(t, I_PUSH, "ttcompat") < 0)
  1135.         fatal(net, "I_PUSH ttcompat");
  1136.     if (ioctl(pty, I_PUSH, "pckt") < 0)
  1137.         fatal(net, "I_PUSH pckt");
  1138. #endif
  1139.  
  1140.     /*
  1141.      * set up the tty modes as we like them to be.
  1142.      */
  1143.     init_termbuf();
  1144. # ifdef    TIOCGWINSZ
  1145.     if (def_row || def_col) {
  1146.         memset((char *)&ws, 0, sizeof(ws));
  1147.         ws.ws_col = def_col;
  1148.         ws.ws_row = def_row;
  1149.         (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
  1150.     }
  1151. # endif
  1152.  
  1153.     /*
  1154.      * Settings for sgtty based systems
  1155.      */
  1156. # ifndef    USE_TERMIO
  1157.     termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
  1158. # endif    /* USE_TERMIO */
  1159.  
  1160.     /*
  1161.      * Settings for UNICOS (and HPUX)
  1162.      */
  1163. # if defined(CRAY) || defined(__hpux)
  1164.     termbuf.c_oflag = OPOST|ONLCR|TAB3;
  1165.     termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
  1166.     termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  1167.     termbuf.c_cflag = EXTB|HUPCL|CS8;
  1168. # endif
  1169.  
  1170.     /*
  1171.      * Settings for all other termios/termio based
  1172.      * systems, other than 4.4BSD.  In 4.4BSD the
  1173.      * kernel does the initial terminal setup.
  1174.      */
  1175. # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
  1176. #  ifndef    OXTABS
  1177. #   define OXTABS    0
  1178. #  endif
  1179.     termbuf.c_lflag |= ECHO;
  1180.     termbuf.c_oflag |= ONLCR|OXTABS;
  1181.     termbuf.c_iflag |= ICRNL;
  1182.     termbuf.c_iflag &= ~IXOFF;
  1183. # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
  1184.     tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
  1185.     tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
  1186. # ifdef    LINEMODE
  1187.     if (waslm)
  1188.         tty_setlinemode(1);
  1189. # endif    /* LINEMODE */
  1190.  
  1191.     /*
  1192.      * Set the tty modes, and make this our controlling tty.
  1193.      */
  1194.     set_termbuf();
  1195.     if (login_tty(t) == -1)
  1196.         fatalperror(net, "login_tty");
  1197. #endif    /* !defined(CRAY) || !defined(NEWINIT) */
  1198.     if (net > 2)
  1199.         (void) close(net);
  1200. #if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1201.     /*
  1202.      * Leave the pty open so that we can write out the rlogin
  1203.      * protocol for /bin/login, if the authentication works.
  1204.      */
  1205. #else
  1206.     if (pty > 2) {
  1207.         (void) close(pty);
  1208.         pty = -1;
  1209.     }
  1210. #endif
  1211. }
  1212.  
  1213. #if    !defined(CRAY) || !defined(NEWINIT)
  1214. #ifndef    O_NOCTTY
  1215. #define    O_NOCTTY    0
  1216. #endif
  1217. /*
  1218.  * Open the specified slave side of the pty,
  1219.  * making sure that we have a clean tty.
  1220.  */
  1221.     int
  1222. cleanopen(line)
  1223.     char *line;
  1224. {
  1225.     register int t;
  1226. #ifdef    UNICOS7x
  1227.     struct secstat secbuf;
  1228. #endif    /* UNICOS7x */
  1229.  
  1230. #ifndef STREAMSPTY
  1231.     /*
  1232.      * Make sure that other people can't open the
  1233.      * slave side of the connection.
  1234.      */
  1235.     (void) chown(line, 0, 0);
  1236.     (void) chmod(line, 0600);
  1237. #endif
  1238.  
  1239. # if !defined(CRAY) && (BSD > 43)
  1240.     (void) revoke(line);
  1241. # endif
  1242. #ifdef    UNICOS7x
  1243.     if (secflag) {
  1244.         if (secstat(line, &secbuf) < 0)
  1245.             return(-1);
  1246.         if (setulvl(secbuf.st_slevel) < 0)
  1247.             return(-1);
  1248.         if (setucmp(secbuf.st_compart) < 0)
  1249.             return(-1);
  1250.     }
  1251. #endif    /* UNICOS7x */
  1252.  
  1253.     t = open(line, O_RDWR|O_NOCTTY);
  1254.  
  1255. #ifdef    UNICOS7x
  1256.     if (secflag) {
  1257.         if (setulvl(sysv.sy_minlvl) < 0)
  1258.             return(-1);
  1259.         if (setucmp(0) < 0)
  1260.             return(-1);
  1261.     }
  1262. #endif    /* UNICOS7x */
  1263.  
  1264.     if (t < 0)
  1265.         return(-1);
  1266.  
  1267.     /*
  1268.      * Hangup anybody else using this ttyp, then reopen it for
  1269.      * ourselves.
  1270.      */
  1271. # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
  1272.     (void) signal(SIGHUP, SIG_IGN);
  1273.     vhangup();
  1274.     (void) signal(SIGHUP, SIG_DFL);
  1275.     t = open(line, O_RDWR|O_NOCTTY);
  1276.     if (t < 0)
  1277.         return(-1);
  1278. # endif
  1279. # if    defined(CRAY) && defined(TCVHUP)
  1280.     {
  1281.         register int i;
  1282.         (void) signal(SIGHUP, SIG_IGN);
  1283.         (void) ioctl(t, TCVHUP, (char *)0);
  1284.         (void) signal(SIGHUP, SIG_DFL);
  1285.  
  1286. #ifdef    UNICOS7x
  1287.         if (secflag) {
  1288.             if (secstat(line, &secbuf) < 0)
  1289.                 return(-1);
  1290.             if (setulvl(secbuf.st_slevel) < 0)
  1291.                 return(-1);
  1292.             if (setucmp(secbuf.st_compart) < 0)
  1293.                 return(-1);
  1294.         }
  1295. #endif    /* UNICOS7x */
  1296.  
  1297.         i = open(line, O_RDWR);
  1298.  
  1299. #ifdef    UNICOS7x
  1300.         if (secflag) {
  1301.             if (setulvl(sysv.sy_minlvl) < 0)
  1302.                 return(-1);
  1303.             if (setucmp(0) < 0)
  1304.                 return(-1);
  1305.         }
  1306. #endif    /* UNICOS7x */
  1307.  
  1308.         if (i < 0)
  1309.             return(-1);
  1310.         (void) close(t);
  1311.         t = i;
  1312.     }
  1313. # endif    /* defined(CRAY) && defined(TCVHUP) */
  1314.     return(t);
  1315. }
  1316. #endif    /* !defined(CRAY) || !defined(NEWINIT) */
  1317.  
  1318. #if BSD <= 43
  1319.  
  1320.     int
  1321. login_tty(t)
  1322.     int t;
  1323. {
  1324.     if (setsid() < 0) {
  1325. #ifdef ultrix
  1326.         /*
  1327.          * The setsid() may have failed because we
  1328.          * already have a pgrp == pid.  Zero out
  1329.          * our pgrp and try again...
  1330.          */
  1331.         if ((setpgrp(0, 0) < 0) || (setsid() < 0))
  1332. #endif
  1333.             fatalperror(net, "setsid()");
  1334.     }
  1335. # ifdef    TIOCSCTTY
  1336.     if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
  1337.         fatalperror(net, "ioctl(sctty)");
  1338. #  if defined(CRAY)
  1339.     /*
  1340.      * Close the hard fd to /dev/ttypXXX, and re-open through
  1341.      * the indirect /dev/tty interface.
  1342.      */
  1343.     close(t);
  1344.     if ((t = open("/dev/tty", O_RDWR)) < 0)
  1345.         fatalperror(net, "open(/dev/tty)");
  1346. #  endif
  1347. # else
  1348.     /*
  1349.      * We get our controlling tty assigned as a side-effect
  1350.      * of opening up a tty device.  But on BSD based systems,
  1351.      * this only happens if our process group is zero.  The
  1352.      * setsid() call above may have set our pgrp, so clear
  1353.      * it out before opening the tty...
  1354.      */
  1355. #  ifndef SOLARIS
  1356.     (void) setpgrp(0, 0);
  1357. #  else
  1358.     (void) setpgrp();
  1359. #  endif
  1360.     close(open(line, O_RDWR));
  1361. # endif
  1362.     if (t != 0)
  1363.         (void) dup2(t, 0);
  1364.     if (t != 1)
  1365.         (void) dup2(t, 1);
  1366.     if (t != 2)
  1367.         (void) dup2(t, 2);
  1368.     if (t > 2)
  1369.         close(t);
  1370.     return(0);
  1371. }
  1372. #endif    /* BSD <= 43 */
  1373.  
  1374. #ifdef    NEWINIT
  1375. char *gen_id = "fe";
  1376. #endif
  1377.  
  1378. /*
  1379.  * startslave(host)
  1380.  *
  1381.  * Given a hostname, do whatever
  1382.  * is necessary to startup the login process on the slave side of the pty.
  1383.  */
  1384.  
  1385. /* ARGSUSED */
  1386.     void
  1387. startslave(host, autologin, autoname)
  1388.     char *host;
  1389.     int autologin;
  1390.     char *autoname;
  1391. {
  1392.     register int i;
  1393.     long time();
  1394.     char name[256];
  1395. #ifdef    NEWINIT
  1396.     extern char *ptyip;
  1397.     struct init_request request;
  1398.     void nologinproc();
  1399.     register int n;
  1400. #endif    /* NEWINIT */
  1401.  
  1402. #if    defined(AUTHENTICATION)
  1403.     if (!autoname || !autoname[0])
  1404.         autologin = 0;
  1405.  
  1406.     if (autologin < auth_level) {
  1407.         fatal(net, "Authorization failed");
  1408.         exit(1);
  1409.     }
  1410. #endif
  1411.  
  1412. #ifndef    NEWINIT
  1413. # ifdef    PARENT_DOES_UTMP
  1414.     utmp_sig_init();
  1415. # endif    /* PARENT_DOES_UTMP */
  1416.  
  1417.     if ((i = fork()) < 0)
  1418.         fatalperror(net, "fork");
  1419.     if (i) {
  1420. # ifdef PARENT_DOES_UTMP
  1421.         /*
  1422.          * Cray parent will create utmp entry for child and send
  1423.          * signal to child to tell when done.  Child waits for signal
  1424.          * before doing anything important.
  1425.          */
  1426.         register int pid = i;
  1427.         void sigjob P((int));
  1428.  
  1429.         setpgrp();
  1430.         utmp_sig_reset();        /* reset handler to default */
  1431.         /*
  1432.          * Create utmp entry for child
  1433.          */
  1434.         (void) time(&wtmp.ut_time);
  1435.         wtmp.ut_type = LOGIN_PROCESS;
  1436.         wtmp.ut_pid = pid;
  1437.         SCPYN(wtmp.ut_user, "LOGIN");
  1438.         SCPYN(wtmp.ut_host, host);
  1439.         SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
  1440. #ifndef    __hpux
  1441.         SCPYN(wtmp.ut_id, wtmp.ut_line+3);
  1442. #else
  1443.         SCPYN(wtmp.ut_id, wtmp.ut_line+7);
  1444. #endif
  1445.         pututline(&wtmp);
  1446.         endutent();
  1447.         if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
  1448.             (void) write(i, (char *)&wtmp, sizeof(struct utmp));
  1449.             (void) close(i);
  1450.         }
  1451. #ifdef    CRAY
  1452.         (void) signal(WJSIGNAL, sigjob);
  1453. #endif
  1454.         utmp_sig_notify(pid);
  1455. # endif    /* PARENT_DOES_UTMP */
  1456.     } else {
  1457.         getptyslave(autologin);
  1458.         start_login(host, autologin, autoname);
  1459.         /*NOTREACHED*/
  1460.     }
  1461. #else    /* NEWINIT */
  1462.  
  1463.     /*
  1464.      * Init will start up login process if we ask nicely.  We only wait
  1465.      * for it to start up and begin normal telnet operation.
  1466.      */
  1467.     if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
  1468.         char tbuf[128];
  1469.         (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
  1470.         fatalperror(net, tbuf);
  1471.     }
  1472.     memset((char *)&request, 0, sizeof(request));
  1473.     request.magic = INIT_MAGIC;
  1474.     SCPYN(request.gen_id, gen_id);
  1475.     SCPYN(request.tty_id, &line[8]);
  1476.     SCPYN(request.host, host);
  1477.     SCPYN(request.term_type, terminaltype ? terminaltype : "network");
  1478. #if    !defined(UNICOS5)
  1479.     request.signal = SIGCLD;
  1480.     request.pid = getpid();
  1481. #endif
  1482. #ifdef BFTPDAEMON
  1483.     /*
  1484.      * Are we working as the bftp daemon?
  1485.      */
  1486.     if (bftpd) {
  1487.         SCPYN(request.exec_name, BFTPPATH);
  1488.     }
  1489. #endif /* BFTPDAEMON */
  1490.     if (write(i, (char *)&request, sizeof(request)) < 0) {
  1491.         char tbuf[128];
  1492.         (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
  1493.         fatalperror(net, tbuf);
  1494.     }
  1495.     (void) close(i);
  1496.     (void) signal(SIGALRM, nologinproc);
  1497.     for (i = 0; ; i++) {
  1498.         char tbuf[128];
  1499.         alarm(15);
  1500.         n = read(pty, ptyip, BUFSIZ);
  1501.         if (i == 3 || n >= 0 || !gotalarm)
  1502.             break;
  1503.         gotalarm = 0;
  1504.         sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
  1505.         (void) write(net, tbuf, strlen(tbuf));
  1506.     }
  1507.     if (n < 0 && gotalarm)
  1508.         fatal(net, "/etc/init didn't start login process");
  1509.     pcc += n;
  1510.     alarm(0);
  1511.     (void) signal(SIGALRM, SIG_DFL);
  1512.  
  1513.     return;
  1514. #endif    /* NEWINIT */
  1515. }
  1516.  
  1517. char    *envinit[3];
  1518. extern char **environ;
  1519.  
  1520.     void
  1521. init_env()
  1522. {
  1523.     extern char *getenv();
  1524.     char **envp;
  1525.  
  1526.     envp = envinit;
  1527.     if (*envp = getenv("TZ"))
  1528.         *envp++ -= 3;
  1529. #if    defined(CRAY) || defined(__hpux)
  1530.     else
  1531.         *envp++ = "TZ=GMT0";
  1532. #endif
  1533.     *envp = 0;
  1534.     environ = envinit;
  1535. }
  1536.  
  1537. #ifndef    NEWINIT
  1538.  
  1539. /*
  1540.  * start_login(host)
  1541.  *
  1542.  * Assuming that we are now running as a child processes, this
  1543.  * function will turn us into the login process.
  1544.  */
  1545.  
  1546.     void
  1547. start_login(host, autologin, name)
  1548.     char *host;
  1549.     int autologin;
  1550.     char *name;
  1551. {
  1552.     register char *cp;
  1553.     register char **argv;
  1554.     char **addarg();
  1555.     extern char *getenv();
  1556. #ifdef    UTMPX
  1557.     register int pid = getpid();
  1558.     struct utmpx utmpx;
  1559. #endif
  1560. #ifdef SOLARIS
  1561.     char *term;
  1562.     char termbuf[64];
  1563. #endif
  1564.  
  1565. #ifdef    UTMPX
  1566.     /*
  1567.      * Create utmp entry for child
  1568.      */
  1569.  
  1570.     memset(&utmpx, 0, sizeof(utmpx));
  1571.     SCPYN(utmpx.ut_user, ".telnet");
  1572.     SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
  1573.     utmpx.ut_pid = pid;
  1574.     utmpx.ut_id[0] = 't';
  1575.     utmpx.ut_id[1] = 'n';
  1576.     utmpx.ut_id[2] = SC_WILDC;
  1577.     utmpx.ut_id[3] = SC_WILDC;
  1578.     utmpx.ut_type = LOGIN_PROCESS;
  1579.     (void) time(&utmpx.ut_tv.tv_sec);
  1580.     if (pututxline(&utmpx) == NULL)
  1581.         fatal(net, "pututxline failed");
  1582. #endif
  1583.  
  1584.     /*
  1585.      * -h : pass on name of host.
  1586.      *        WARNING:  -h is accepted by login if and only if
  1587.      *            getuid() == 0.
  1588.      * -p : don't clobber the environment (so terminal type stays set).
  1589.      *
  1590.      * -f : force this login, he has already been authenticated
  1591.      */
  1592.     argv = addarg(0, "login");
  1593.  
  1594. #if    !defined(NO_LOGIN_H)
  1595.  
  1596. # if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1597.     /*
  1598.      * Don't add the "-h host" option if we are going
  1599.      * to be adding the "-r host" option down below...
  1600.      */
  1601.     if ((auth_level < 0) || (autologin != AUTH_VALID))
  1602. # endif
  1603.     {
  1604.         argv = addarg(argv, "-h");
  1605.         argv = addarg(argv, host);
  1606. #ifdef    SOLARIS
  1607.         /*
  1608.          * SVR4 version of -h takes TERM= as second arg, or -
  1609.          */
  1610.         term = getenv("TERM");
  1611.         if (term == NULL || term[0] == 0) {
  1612.             term = "-";
  1613.         } else {
  1614.             strcpy(termbuf, "TERM=");
  1615.             strncat(termbuf, term, sizeof(termbuf) - 6);
  1616.             term = termbuf;
  1617.         }
  1618.         argv = addarg(argv, term);
  1619. #endif
  1620.     }
  1621. #endif
  1622. #if    !defined(NO_LOGIN_P)
  1623.     argv = addarg(argv, "-p");
  1624. #endif
  1625. #ifdef    LINEMODE
  1626.     /*
  1627.      * Set the environment variable "LINEMODE" to either
  1628.      * "real" or "kludge" if we are operating in either
  1629.      * real or kludge linemode.
  1630.      */
  1631.     if (lmodetype == REAL_LINEMODE)
  1632.         setenv("LINEMODE", "real", 1);
  1633. # ifdef KLUDGELINEMODE
  1634.     else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
  1635.         setenv("LINEMODE", "kludge", 1);
  1636. # endif
  1637. #endif
  1638. #ifdef    BFTPDAEMON
  1639.     /*
  1640.      * Are we working as the bftp daemon?  If so, then ask login
  1641.      * to start bftp instead of shell.
  1642.      */
  1643.     if (bftpd) {
  1644.         argv = addarg(argv, "-e");
  1645.         argv = addarg(argv, BFTPPATH);
  1646.     } else 
  1647. #endif
  1648. #if    defined (SecurID)
  1649.     /*
  1650.      * don't worry about the -f that might get sent.
  1651.      * A -s is supposed to override it anyhow.
  1652.      */
  1653.     if (require_SecurID)
  1654.         argv = addarg(argv, "-s");
  1655. #endif
  1656. #if    defined (AUTHENTICATION)
  1657.     if (auth_level >= 0 && autologin == AUTH_VALID) {
  1658. # if    !defined(NO_LOGIN_F)
  1659.         argv = addarg(argv, "-f");
  1660.         argv = addarg(argv, name);
  1661. # else
  1662. #  if defined(LOGIN_R)
  1663.         /*
  1664.          * We don't have support for "login -f", but we
  1665.          * can fool /bin/login into thinking that we are
  1666.          * rlogind, and allow us to log in without a
  1667.          * password.  The rlogin protocol expects
  1668.          *    local-user\0remote-user\0term/speed\0
  1669.          */
  1670.  
  1671.         if (pty > 2) {
  1672.             register char *cp;
  1673.             char speed[128];
  1674.             int isecho, israw, xpty, len;
  1675.             extern int def_rspeed;
  1676. #  ifndef LOGIN_HOST
  1677.             /*
  1678.              * Tell login that we are coming from "localhost".
  1679.              * If we passed in the real host name, then the
  1680.              * user would have to allow .rhost access from
  1681.              * every machine that they want authenticated
  1682.              * access to work from, which sort of defeats
  1683.              * the purpose of an authenticated login...
  1684.              * So, we tell login that the session is coming
  1685.              * from "localhost", and the user will only have
  1686.              * to have "localhost" in their .rhost file.
  1687.              */
  1688. #            define LOGIN_HOST "localhost"
  1689. #  endif
  1690.             argv = addarg(argv, "-r");
  1691.             argv = addarg(argv, LOGIN_HOST);
  1692.  
  1693.             xpty = pty;
  1694. # ifndef  STREAMSPTY
  1695.             pty = 0;
  1696. # else
  1697.             ttyfd = 0;
  1698. # endif
  1699.             init_termbuf();
  1700.             isecho = tty_isecho();
  1701.             israw = tty_israw();
  1702.             if (isecho || !israw) {
  1703.                 tty_setecho(0);        /* Turn off echo */
  1704.                 tty_setraw(1);        /* Turn on raw */
  1705.                 set_termbuf();
  1706.             }
  1707.             len = strlen(name)+1;
  1708.             write(xpty, name, len);
  1709.             write(xpty, name, len);
  1710.             sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
  1711.                 (def_rspeed > 0) ? def_rspeed : 9600);
  1712.             len = strlen(speed)+1;
  1713.             write(xpty, speed, len);
  1714.  
  1715.             if (isecho || !israw) {
  1716.                 init_termbuf();
  1717.                 tty_setecho(isecho);
  1718.                 tty_setraw(israw);
  1719.                 set_termbuf();
  1720.                 if (!israw) {
  1721.                     /*
  1722.                      * Write a newline to ensure
  1723.                      * that login will be able to
  1724.                      * read the line...
  1725.                      */
  1726.                     write(xpty, "\n", 1);
  1727.                 }
  1728.             }
  1729.             pty = xpty;
  1730.         }
  1731. #  else
  1732.         argv = addarg(argv, name);
  1733. #  endif
  1734. # endif
  1735.     } else
  1736. #endif
  1737.     if (getenv("USER")) {
  1738.         argv = addarg(argv, getenv("USER"));
  1739. #if    defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
  1740.         {
  1741.             register char **cpp;
  1742.             for (cpp = environ; *cpp; cpp++)
  1743.                 argv = addarg(argv, *cpp);
  1744.         }
  1745. #endif
  1746.         /*
  1747.          * Assume that login will set the USER variable
  1748.          * correctly.  For SysV systems, this means that
  1749.          * USER will no longer be set, just LOGNAME by
  1750.          * login.  (The problem is that if the auto-login
  1751.          * fails, and the user then specifies a different
  1752.          * account name, he can get logged in with both
  1753.          * LOGNAME and USER in his environment, but the
  1754.          * USER value will be wrong.
  1755.          */
  1756.         unsetenv("USER");
  1757.     }
  1758. #ifdef    SOLARIS
  1759.     else {
  1760.         char **p;
  1761.  
  1762.         argv = addarg(argv, "");    /* no login name */
  1763.         for (p = environ; *p; p++) {
  1764.             argv = addarg(argv, *p);
  1765.         }
  1766.     }
  1767. #endif    /* SOLARIS */
  1768. #if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
  1769.     if (pty > 2)
  1770.         close(pty);
  1771. #endif
  1772.     closelog();
  1773.     /*
  1774.      * This sleep(1) is in here so that telnetd can
  1775.      * finish up with the tty.  There's a race condition
  1776.      * the login banner message gets lost...
  1777.      */
  1778.     sleep(1);
  1779.     execv(_PATH_LOGIN, argv);
  1780.  
  1781.     syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
  1782.     fatalperror(net, _PATH_LOGIN);
  1783.     /*NOTREACHED*/
  1784. }
  1785.  
  1786.     char **
  1787. addarg(argv, val)
  1788.     register char **argv;
  1789.     register char *val;
  1790. {
  1791.     register char **cpp;
  1792.  
  1793.     if (argv == NULL) {
  1794.         /*
  1795.          * 10 entries, a leading length, and a null
  1796.          */
  1797.         argv = (char **)malloc(sizeof(*argv) * 12);
  1798.         if (argv == NULL)
  1799.             return(NULL);
  1800.         *argv++ = (char *)10;
  1801.         *argv = (char *)0;
  1802.     }
  1803.     for (cpp = argv; *cpp; cpp++)
  1804.         ;
  1805.     if (cpp == &argv[(int)argv[-1]]) {
  1806.         --argv;
  1807.         *argv = (char *)((int)(*argv) + 10);
  1808.         argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
  1809.         if (argv == NULL)
  1810.             return(NULL);
  1811.         argv++;
  1812.         cpp = &argv[(int)argv[-1] - 10];
  1813.     }
  1814.     *cpp++ = val;
  1815.     *cpp = 0;
  1816.     return(argv);
  1817. }
  1818. #endif    /* NEWINIT */
  1819.  
  1820. /*
  1821.  * cleanup()
  1822.  *
  1823.  * This is the routine to call when we are all through, to
  1824.  * clean up anything that needs to be cleaned up.
  1825.  */
  1826.     /* ARGSUSED */
  1827.     void
  1828. cleanup(sig)
  1829.     int sig;
  1830. {
  1831. #ifndef    PARENT_DOES_UTMP
  1832. # if (BSD > 43) || defined(convex)
  1833.     char *p;
  1834.  
  1835.     p = line + sizeof("/dev/") - 1;
  1836.     if (logout(p))
  1837.         logwtmp(p, "", "");
  1838.     (void)chmod(line, 0666);
  1839.     (void)chown(line, 0, 0);
  1840.     *p = 'p';
  1841.     (void)chmod(line, 0666);
  1842.     (void)chown(line, 0, 0);
  1843.     (void) shutdown(net, 2);
  1844.     exit(1);
  1845. # else
  1846.     void rmut();
  1847.  
  1848.     rmut();
  1849.     vhangup();    /* XXX */
  1850.     (void) shutdown(net, 2);
  1851.     exit(1);
  1852. # endif
  1853. #else    /* PARENT_DOES_UTMP */
  1854. # ifdef    NEWINIT
  1855.     (void) shutdown(net, 2);
  1856.     exit(1);
  1857. # else    /* NEWINIT */
  1858. #  ifdef CRAY
  1859.     static int incleanup = 0;
  1860.     register int t;
  1861.     int child_status; /* status of child process as returned by waitpid */
  1862.     int flags = WNOHANG|WUNTRACED;
  1863.  
  1864.     /*
  1865.      * 1: Pick up the zombie, if we are being called
  1866.      *    as the signal handler.
  1867.      * 2: If we are a nested cleanup(), return.
  1868.      * 3: Try to clean up TMPDIR.
  1869.      * 4: Fill in utmp with shutdown of process.
  1870.      * 5: Close down the network and pty connections.
  1871.      * 6: Finish up the TMPDIR cleanup, if needed.
  1872.      */
  1873.     if (sig == SIGCHLD) {
  1874.         while (waitpid(-1, &child_status, flags) > 0)
  1875.             ;    /* VOID */
  1876.         /* Check if the child process was stopped
  1877.          * rather than exited.  We want cleanup only if
  1878.          * the child has died.
  1879.          */
  1880.         if (WIFSTOPPED(child_status)) {
  1881.             return;
  1882.         }
  1883.     }
  1884.     t = sigblock(sigmask(SIGCHLD));
  1885.     if (incleanup) {
  1886.         sigsetmask(t);
  1887.         return;
  1888.     }
  1889.     incleanup = 1;
  1890.     sigsetmask(t);
  1891. #ifdef    UNICOS7x
  1892.     if (secflag) {
  1893.         /*
  1894.          *    We need to set ourselves back to a null
  1895.          *    label to clean up.
  1896.          */
  1897.  
  1898.         setulvl(sysv.sy_minlvl);
  1899.         setucmp((long)0);
  1900.     }
  1901. #endif    /* UNICOS7x */
  1902.  
  1903.     t = cleantmp(&wtmp);
  1904.     setutent();    /* just to make sure */
  1905. #  endif /* CRAY */
  1906.     rmut(line);
  1907.     close(pty);
  1908.     (void) shutdown(net, 2);
  1909. #  ifdef CRAY
  1910.     if (t == 0)
  1911.         cleantmp(&wtmp);
  1912. #  endif /* CRAY */
  1913.     exit(1);
  1914. # endif    /* NEWINT */
  1915. #endif    /* PARENT_DOES_UTMP */
  1916. }
  1917.  
  1918. #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
  1919. /*
  1920.  * _utmp_sig_rcv
  1921.  * utmp_sig_init
  1922.  * utmp_sig_wait
  1923.  *    These three functions are used to coordinate the handling of
  1924.  *    the utmp file between the server and the soon-to-be-login shell.
  1925.  *    The server actually creates the utmp structure, the child calls
  1926.  *    utmp_sig_wait(), until the server calls utmp_sig_notify() and
  1927.  *    signals the future-login shell to proceed.
  1928.  */
  1929. static int caught=0;        /* NZ when signal intercepted */
  1930. static void (*func)();        /* address of previous handler */
  1931.  
  1932.     void
  1933. _utmp_sig_rcv(sig)
  1934.     int sig;
  1935. {
  1936.     caught = 1;
  1937.     (void) signal(SIGUSR1, func);
  1938. }
  1939.  
  1940.     void
  1941. utmp_sig_init()
  1942. {
  1943.     /*
  1944.      * register signal handler for UTMP creation
  1945.      */
  1946.     if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
  1947.         fatalperror(net, "telnetd/signal");
  1948. }
  1949.  
  1950.     void
  1951. utmp_sig_reset()
  1952. {
  1953.     (void) signal(SIGUSR1, func);    /* reset handler to default */
  1954. }
  1955.  
  1956. # ifdef __hpux
  1957. # define sigoff() /* do nothing */
  1958. # define sigon() /* do nothing */
  1959. # endif
  1960.  
  1961.     void
  1962. utmp_sig_wait()
  1963. {
  1964.     /*
  1965.      * Wait for parent to write our utmp entry.
  1966.      */
  1967.     sigoff();
  1968.     while (caught == 0) {
  1969.         pause();    /* wait until we get a signal (sigon) */
  1970.         sigoff();    /* turn off signals while we check caught */
  1971.     }
  1972.     sigon();        /* turn on signals again */
  1973. }
  1974.  
  1975.     void
  1976. utmp_sig_notify(pid)
  1977. {
  1978.     kill(pid, SIGUSR1);
  1979. }
  1980.  
  1981. # ifdef CRAY
  1982. static int gotsigjob = 0;
  1983.  
  1984.     /*ARGSUSED*/
  1985.     void
  1986. sigjob(sig)
  1987.     int sig;
  1988. {
  1989.     register int jid;
  1990.     register struct jobtemp *jp;
  1991.  
  1992.     while ((jid = waitjob(NULL)) != -1) {
  1993.         if (jid == 0) {
  1994.             return;
  1995.         }
  1996.         gotsigjob++;
  1997.         jobend(jid, NULL, NULL);
  1998.     }
  1999. }
  2000.  
  2001. /*
  2002.  *    jid_getutid:
  2003.  *        called by jobend() before calling cleantmp()
  2004.  *        to find the correct $TMPDIR to cleanup.
  2005.  */
  2006.  
  2007.     struct utmp *
  2008. jid_getutid(jid)
  2009.     int jid;
  2010. {
  2011.     struct utmp *cur = NULL;
  2012.  
  2013.     setutent();    /* just to make sure */
  2014.     while (cur = getutent()) {
  2015.         if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
  2016.             return(cur);
  2017.         }
  2018.     }
  2019.  
  2020.     return(0);
  2021. }
  2022.  
  2023. /*
  2024.  * Clean up the TMPDIR that login created.
  2025.  * The first time this is called we pick up the info
  2026.  * from the utmp.  If the job has already gone away,
  2027.  * then we'll clean up and be done.  If not, then
  2028.  * when this is called the second time it will wait
  2029.  * for the signal that the job is done.
  2030.  */
  2031.     int
  2032. cleantmp(wtp)
  2033.     register struct utmp *wtp;
  2034. {
  2035.     struct utmp *utp;
  2036.     static int first = 1;
  2037.     register int mask, omask, ret;
  2038.     extern struct utmp *getutid P((const struct utmp *_Id));
  2039.  
  2040.  
  2041.     mask = sigmask(WJSIGNAL);
  2042.  
  2043.     if (first == 0) {
  2044.         omask = sigblock(mask);
  2045.         while (gotsigjob == 0)
  2046.             sigpause(omask);
  2047.         return(1);
  2048.     }
  2049.     first = 0;
  2050.     setutent();    /* just to make sure */
  2051.  
  2052.     utp = getutid(wtp);
  2053.     if (utp == 0) {
  2054.         syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
  2055.         return(-1);
  2056.     }
  2057.     /*
  2058.      * Nothing to clean up if the user shell was never started.
  2059.      */
  2060.     if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
  2061.         return(1);
  2062.  
  2063.     /*
  2064.      * Block the WJSIGNAL while we are in jobend().
  2065.      */
  2066.     omask = sigblock(mask);
  2067.     ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
  2068.     sigsetmask(omask);
  2069.     return(ret);
  2070. }
  2071.  
  2072.     int
  2073. jobend(jid, path, user)
  2074.     register int jid;
  2075.     register char *path;
  2076.     register char *user;
  2077. {
  2078.     static int saved_jid = 0;
  2079.     static int pty_saved_jid = 0;
  2080.     static char saved_path[sizeof(wtmp.ut_tpath)+1];
  2081.     static char saved_user[sizeof(wtmp.ut_user)+1];
  2082.  
  2083.     /*
  2084.      * this little piece of code comes into play
  2085.      * only when ptyreconnect is used to reconnect
  2086.      * to an previous session.
  2087.      *
  2088.      * this is the only time when the
  2089.      * "saved_jid != jid" code is executed.
  2090.      */
  2091.  
  2092.     if ( saved_jid && saved_jid != jid ) {
  2093.         if (!path) {    /* called from signal handler */
  2094.             pty_saved_jid = jid;
  2095.         } else {
  2096.             pty_saved_jid = saved_jid;
  2097.         }
  2098.     }
  2099.  
  2100.     if (path) {
  2101.         strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
  2102.         strncpy(saved_user, user, sizeof(wtmp.ut_user));
  2103.         saved_path[sizeof(saved_path)] = '\0';
  2104.         saved_user[sizeof(saved_user)] = '\0';
  2105.     }
  2106.     if (saved_jid == 0) {
  2107.         saved_jid = jid;
  2108.         return(0);
  2109.     }
  2110.  
  2111.     /* if the jid has changed, get the correct entry from the utmp file */
  2112.  
  2113.     if ( saved_jid != jid ) {
  2114.         struct utmp *utp = NULL;
  2115.         struct utmp *jid_getutid();
  2116.  
  2117.         utp = jid_getutid(pty_saved_jid);
  2118.  
  2119.         if (utp == 0) {
  2120.             syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
  2121.             return(-1);
  2122.         }
  2123.  
  2124.         cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
  2125.         return(1);
  2126.     }
  2127.  
  2128.     cleantmpdir(jid, saved_path, saved_user);
  2129.     return(1);
  2130. }
  2131.  
  2132. /*
  2133.  * Fork a child process to clean up the TMPDIR
  2134.  */
  2135. cleantmpdir(jid, tpath, user)
  2136.     register int jid;
  2137.     register char *tpath;
  2138.     register char *user;
  2139. {
  2140.     switch(fork()) {
  2141.     case -1:
  2142.         syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
  2143.                             tpath);
  2144.         break;
  2145.     case 0:
  2146.         execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
  2147.         syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
  2148.                             tpath, CLEANTMPCMD);
  2149.         exit(1);
  2150.     default:
  2151.         /*
  2152.          * Forget about child.  We will exit, and
  2153.          * /etc/init will pick it up.
  2154.          */
  2155.         break;
  2156.     }
  2157. }
  2158. # endif /* CRAY */
  2159. #endif    /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
  2160.  
  2161. /*
  2162.  * rmut()
  2163.  *
  2164.  * This is the function called by cleanup() to
  2165.  * remove the utmp entry for this person.
  2166.  */
  2167.  
  2168. #ifdef    UTMPX
  2169.     void
  2170. rmut()
  2171. {
  2172.     register f;
  2173.     int found = 0;
  2174.     struct utmp *u, *utmp;
  2175.     int nutmp;
  2176.     struct stat statbf;
  2177.  
  2178.     struct utmpx *utxp, utmpx;
  2179.  
  2180.     /*
  2181.      * This updates the utmpx and utmp entries and make a wtmp/x entry
  2182.      */
  2183.  
  2184.     SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
  2185.     utxp = getutxline(&utmpx);
  2186.     if (utxp) {
  2187.         utxp->ut_type = DEAD_PROCESS;
  2188.         utxp->ut_exit.e_termination = 0;
  2189.         utxp->ut_exit.e_exit = 0;
  2190.         (void) time(&utmpx.ut_tv.tv_sec);
  2191.         utmpx.ut_tv.tv_usec = 0;
  2192.         modutx(utxp);
  2193.     }
  2194.     endutxent();
  2195. }  /* end of rmut */
  2196. #endif
  2197.  
  2198. #if    !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
  2199.     void
  2200. rmut()
  2201. {
  2202.     register f;
  2203.     int found = 0;
  2204.     struct utmp *u, *utmp;
  2205.     int nutmp;
  2206.     struct stat statbf;
  2207.  
  2208.     f = open(utmpf, O_RDWR);
  2209.     if (f >= 0) {
  2210.         (void) fstat(f, &statbf);
  2211.         utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
  2212.         if (!utmp)
  2213.             syslog(LOG_ERR, "utmp malloc failed");
  2214.         if (statbf.st_size && utmp) {
  2215.             nutmp = read(f, (char *)utmp, (int)statbf.st_size);
  2216.             nutmp /= sizeof(struct utmp);
  2217.         
  2218.             for (u = utmp ; u < &utmp[nutmp] ; u++) {
  2219.                 if (SCMPN(u->ut_line, line+5) ||
  2220.                     u->ut_name[0]==0)
  2221.                     continue;
  2222.                 (void) lseek(f, ((long)u)-((long)utmp), L_SET);
  2223.                 SCPYN(u->ut_name, "");
  2224.                 SCPYN(u->ut_host, "");
  2225.                 (void) time(&u->ut_time);
  2226.                 (void) write(f, (char *)u, sizeof(wtmp));
  2227.                 found++;
  2228.             }
  2229.         }
  2230.         (void) close(f);
  2231.     }
  2232.     if (found) {
  2233.         f = open(wtmpf, O_WRONLY|O_APPEND);
  2234.         if (f >= 0) {
  2235.             SCPYN(wtmp.ut_line, line+5);
  2236.             SCPYN(wtmp.ut_name, "");
  2237.             SCPYN(wtmp.ut_host, "");
  2238.             (void) time(&wtmp.ut_time);
  2239.             (void) write(f, (char *)&wtmp, sizeof(wtmp));
  2240.             (void) close(f);
  2241.         }
  2242.     }
  2243.     (void) chmod(line, 0666);
  2244.     (void) chown(line, 0, 0);
  2245.     line[strlen("/dev/")] = 'p';
  2246.     (void) chmod(line, 0666);
  2247.     (void) chown(line, 0, 0);
  2248. }  /* end of rmut */
  2249. #endif    /* CRAY */
  2250.  
  2251. #ifdef __hpux
  2252. rmut (line)
  2253. char *line;
  2254. {
  2255.     struct utmp utmp;
  2256.     struct utmp *utptr;
  2257.     int fd;            /* for /etc/wtmp */
  2258.  
  2259.     utmp.ut_type = USER_PROCESS;
  2260.     (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
  2261.     (void) setutent();
  2262.     utptr = getutid(&utmp);
  2263.     /* write it out only if it exists */
  2264.     if (utptr) {
  2265.         utptr->ut_type = DEAD_PROCESS;
  2266.         utptr->ut_time = time((long *) 0);
  2267.         (void) pututline(utptr);
  2268.         /* set wtmp entry if wtmp file exists */
  2269.         if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
  2270.             (void) write(fd, utptr, sizeof(utmp));
  2271.             (void) close(fd);
  2272.         }
  2273.     }
  2274.     (void) endutent();
  2275.  
  2276.     (void) chmod(line, 0666);
  2277.     (void) chown(line, 0, 0);
  2278.     line[14] = line[13];
  2279.     line[13] = line[12];
  2280.     line[8] = 'm';
  2281.     line[9] = '/';
  2282.     line[10] = 'p';
  2283.     line[11] = 't';
  2284.     line[12] = 'y';
  2285.     (void) chmod(line, 0666);
  2286.     (void) chown(line, 0, 0);
  2287. }
  2288. #endif
  2289.